package jzbank.util;

import ch.ethz.ssh2.ChannelCondition;
import ch.ethz.ssh2.Connection;
import ch.ethz.ssh2.Session;
import ch.ethz.ssh2.StreamGobbler;

import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.nio.charset.Charset;

public class RemoteShellExecutor  {

	private Connection conn;
	/** 远程机器IP */
	private String ip;
	/** 用户名 */
	private String osUsername;
	/** 密码 */
	private String password;
	private String charset = Charset.defaultCharset().toString();

	private static final int TIME_OUT = 1000 * 5 * 60;
	private boolean loginFlag = false;

	/**
	* 构造函数
	* @param ip
	* @param usr
	* @param pasword
	*/
	public RemoteShellExecutor(String ip, String usr, String pasword) {
		this.ip = ip;
		this.osUsername = usr;
		this.password = pasword;
	}

	/** 
	 * 登录
	 * 
	 * @return
	 * @throws IOException
	 */
	private boolean login() throws IOException {
		if (!this.loginFlag){
			conn = new Connection(ip);
			conn.connect();
			this.loginFlag = conn.authenticateWithPassword(osUsername, password);
		}
		return this.loginFlag;
	}
	
	public void closeConnection(){
		if(conn != null){
			conn.close();
		}
	}

	/**
	 * 执行脚本
	 * 
	 * @param cmds
	 * @return
	 * @throws Exception
	 */
	public int exec(String cmds) throws Exception {
		InputStream stdOut = null;
		InputStream stdErr = null;
		String outStr = "";
		String outErr = "";
		int ret = -1;
		try {
			if (login()) {
				// Open a new {@link Session} on this connection
				Session session = conn.openSession();
				// Execute a command on the remote machine.
				session.execCommand(cmds);

				stdOut = new StreamGobbler(session.getStdout());
				outStr = processStream(stdOut, charset);

				stdErr = new StreamGobbler(session.getStderr());
				outErr = processStream(stdErr, charset);

				session.waitForCondition(ChannelCondition.EXIT_STATUS, TIME_OUT);

				System.out.println("outStr=" + outStr);
				System.out.println("outErr=" + outErr);

				ret = session.getExitStatus();
				session.close();
			} else {
				throw new Exception("登录远程机器失败" + ip); // 自定义异常类 实现略
			}
		} finally {
//			if (conn != null) {
//				conn.close();
//			}
			if (stdOut != null){
				stdOut.close();
			}
			if (stdErr != null){
				stdErr.close();
			}
		}
		return ret;
	}

	/**
	 * @param in
	 * @param charset
	 * @return
	 * @throws IOException
	 * @throws UnsupportedEncodingException
	 */
	private String processStream(InputStream in, String charset) throws Exception {
		byte[] buf = new byte[1024];
		StringBuilder sb = new StringBuilder();
		while (in.read(buf) != -1) {
			sb.append(new String(buf, charset));
		}
		return sb.toString();
	}

	public int sh(String cmds) throws Exception {
		return this.exec(cmds);	
	}
}
